import L from "leaflet";
import * as turf from "@turf/turf";
import "leaflet-polylinedecorator";
import "leaflet-rotatedmarker";

L.TrackLine = class {
  constructor(trackList, options = {}) {
    this.map = null;
    this.notPassedLine = null;
    this.passedLine = null;
    this.trackMarker = null;
    this.startMarker = null;
    this.endMarker = null;
    this.intervalId = null;
    this.trackList = trackList;
    this.eventEmitter = new EventTarget();
    this.options = {
      startIconOptions: options.startIconOptions ?? {},
      endIconOptions: options.endIconOptions ?? {},
      markerIconOptions: options.markerIconOptions ?? {},
      location: options.location ?? false,
      speed: options.speed ?? 500,
      notPassedLineOptions: options.notPassedLineOptions ?? {},
      passedLineOptions: options.passedLineOptions ?? {}
    };
    this.coordinates = this.trackList.map(v => [v.lng, v.lat]);
  }

  addTo(map) {
    this.map = map;
    const { startIconOptions, endIconOptions, markerIconOptions, location,notPassedLineOptions,passedLineOptions } = this.options;
    this.startMarker = L.marker(this.trackList[0], { icon: L.icon(startIconOptions) }).addTo(this.map);
    this.notPassedLine = L.polyline(this.trackList, notPassedLineOptions).addTo(this.map);
    if (location) {
      this.passedLine = L.polyline(this.trackList, passedLineOptions).addTo(this.map);       
      this.trackMarker = L.marker(this.trackList[this.trackList.length-1], { icon: L.icon(markerIconOptions) }).addTo(this.map);      
      this.map.panTo(this.trackList[this.trackList.length-1], { animate:true });  
      this.calcTrackMarkerRotate(this.coordinates, this.coordinates.length-1);     
    } else {
      this.endMarker = L.marker(this.trackList[this.trackList.length - 1], { icon: L.icon(endIconOptions) }).addTo(this.map);
      this.passedLine = L.polyline([], passedLineOptions).addTo(this.map);
      this.trackMarker = L.marker(this.trackList[0], { icon: L.icon(markerIconOptions) }).addTo(this.map);
      this.map.panTo(this.trackList[0], { animate:true });
      this.calcTrackMarkerRotate(this.coordinates, 1);
    }   
    return this; 
  }

  updateTrack(trackList, location) {    
    this.trackList = trackList;
    this.coordinates = this.trackList.map(v => [v.lng, v.lat]);
    this.passedLine.setLatLngs(this.trackList);
    this.trackMarker.setLatLng(this.trackList[this.trackList.length-1]);
    if (location) {
      this.map.panTo(this.trackList[this.trackList.length-1], {animate: true});
    }
    this.calcTrackMarkerRotate(this.coordinates, this.coordinates.length-1);
  }

  start(index) {  
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    }  
    if (index == this.trackList.length-1) {
      index = 0;       
    }
    this.passedLine.setLatLngs(this.trackList.slice(0, index+1));
    this.trackMarker.setLatLng(this.trackList[index]);
    if (index !== 0) {           
      this.calcTrackMarkerRotate(this.coordinates, index);
    } else {
      this.calcTrackMarkerRotate(this.coordinates, 1);
    }    
    const event = new CustomEvent('progress', { detail: index });
    this.eventEmitter.dispatchEvent(event);
    this.intervalId = setInterval(() => {
      if (index < this.trackList.length) {
        this.passedLine.setLatLngs(this.trackList.slice(0, index+1));
        this.trackMarker.setLatLng(this.trackList[index]);
        if (index !== 0) {           
          this.calcTrackMarkerRotate(this.coordinates, index);
        } else {
          this.calcTrackMarkerRotate(this.coordinates, 1);
        }
        const event = new CustomEvent('progress', { detail: index });
        this.eventEmitter.dispatchEvent(event);
        index += 1;      
      } else {
        clearInterval(this.intervalId);
        this.intervalId = null;
      }         
    }, this.options.speed);
  }

  pause() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    }      
  }  

  setSpeed(index, speed) {
    this.options.speed = speed;
    if (this.intervalId) {      
      this.start(index);
    }
  }  

  setProgress(index) {
    if (this.intervalId) {
      this.start(index);
    } else {
      this.pause();
      this.passedLine.setLatLngs(this.trackList.slice(0, index+1));
      this.trackMarker.setLatLng(this.trackList[index]);
      const event = new CustomEvent('progress', { detail: index });
      this.eventEmitter.dispatchEvent(event);
      if (index !== 0) {           
        this.calcTrackMarkerRotate(this.coordinates, index);
      } else {
        this.calcTrackMarkerRotate(this.coordinates, 1);
      }   
    }             
  }  

  remove(){
    if (this.notPassedLine) {
      this.map.removeLayer(this.notPassedLine);
    }
    if (this.passedLine) {
      this.map.removeLayer(this.passedLine);
    }
    if (this.trackMarker) {
      this.map.removeLayer(this.trackMarker);
    }
    if (this.startMarker) {
      this.map.removeLayer(this.startMarker);
    }
    if (this.endMarker) {
      this.map.removeLayer(this.endMarker);
    }
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    } 
  }

  calcTrackMarkerRotate(coordinates, index) {
    const direction = turf.bearing(coordinates[index-1], coordinates[index]);
    this.trackMarker.setRotationAngle(direction/2);
    this.trackMarker.setRotationOrigin("center"); 
  }
}